﻿using System;
using System.IO;
using NUnit.Framework;

namespace CodeGenerator
{
	[TestFixture]
	public class CompoundEnumerableGenerator
	{
		public static readonly string Header =
			@"using System;
using System.Collections.Generic;

namespace IllicitOnion.LinqDimensions
{";

		public static readonly string Footer = "\r\n}";

		[Test]
		public void GenerateText()
		{
			Console.WriteLine(Generate(2, 3));
		}

		[Test]
		public void SaveAsFile()
		{
			File.WriteAllText(IEnumerableGenerator.Path + "CompoundEnumerable.cs", Generate(2, 3));
		}

		//TODO: Factor out repetition
		//TODO: Factor out commonality with IEnumerableGenerator

		private static string Generate(int from, int to)
		{
			var str = Header;
			for (var numberOfArgs = from; numberOfArgs <= to; ++numberOfArgs)
			{
				var numberOfLeftArgs = numberOfArgs - 1;
				var genericTypes = IEnumerableGenerator.GetGenericTypes(numberOfArgs);
				var leftGenericTypes = IEnumerableGenerator.GetGenericTypes(numberOfLeftArgs);

				str += "\r\n\tpublic partial class CompoundEnumerable" + genericTypes + " : IEnumerable" + genericTypes;
				str += "\r\n\t{";
				str += "\r\n\t\tprotected readonly IEnumerable" + leftGenericTypes + " m_Left;";
				str += "\r\n\t\tprotected readonly IEnumerable<T" + numberOfLeftArgs + "> m_Right;";
				str += "\r\n\t\tpublic CompoundEnumerable(";
				for (var arg = 0; arg < numberOfArgs; ++arg)
				{
					if (arg != 0)
					{
						str += ", ";
					}
					str += "IEnumerable<T" + arg + "> t" + arg + "s";
				}
				str += ")";
				str += "\r\n\t\t{";
				for (var arg = 0; arg < numberOfArgs; ++arg)
				{
					str += "\r\n\t\t\tif (t" + arg + "s == null)\r\n\t\t\t{\r\n\t\t\t\tthrow new ArgumentNullException(\"t" + arg + "s\");\r\n\t\t\t}";
				}
				if (numberOfLeftArgs == 1)
				{
					str += "\r\n\t\t\tm_Left = t0s;"; 
				}
				else
				{
					str += "\r\n\t\t\tm_Left = new CompoundEnumerable" + leftGenericTypes + "(";
					for (var arg = 0; arg < numberOfLeftArgs; ++arg)
					{
						if (arg != 0)
						{
							str += ", ";
						}
						str += "t" + arg + "s";
					}
					str += ");";
				}
				str += "\r\n\t\t\tm_Right = t" + numberOfLeftArgs + "s;";
				str += "\r\n\t\t}";
				if (numberOfLeftArgs > 1)
				{
					str += "\r\n\t\tpublic CompoundEnumerable(IEnumerable" + leftGenericTypes + "left, IEnumerable<T" + numberOfLeftArgs + "> right)";
					str += "\r\n\t\t{";
					str += "\r\n\t\t\tif (left == null) {\r\n\t\t\t\tthrow new ArgumentNullException(\"left\");\r\n\t\t\t}";
					str += "\r\n\t\t\tif (right == null) {\r\n\t\t\t\tthrow new ArgumentNullException(\"right\");\r\n\t\t\t}";
					str += "\r\n\t\t\tm_Left = left;";
					str += "\r\n\t\t\tm_Right = right;";
					str += "\r\n\t\t}";
				}
				str += "\r\n\t}";
			}
			str += Footer;
			return str;
		}
	}
}
